package os;

import java.util.Hashtable;

/**
 * Super class of all processes developed for the {@link os.MiniOS}. Any process
 * is composed of a set of threads which get executed by the
 * {@link os.kernelProcess.SchedulerThread}. There is a main thread of execution
 * in each process which is started when the process is created. The process by
 * itself is just a data-structure. Threads contain the execution code.
 * <b>Threads can spwan new threads by requesting this from the
 * {@link os.MiniOS}</b>
 * 
 * @author Ahmed El-Eryan
 * 
 */
public abstract class MiniProcess
{

	/**
	 * Pid of the process.
	 */
	protected String pid;

	/**
	 * Name of the process. This is typically the command used to run the
	 * process.
	 */
	protected String name;

	/**
	 * Owner of the process.
	 */
	protected String user;

	/**
	 * Description of the process. It is shown in the Process Monitor tab.
	 */
	protected String description;

	/**
	 * Indicates whether the user has suspended the process or not.
	 */
	protected boolean suspended = false;

	/**
	 * Container for the process threads.
	 */
	protected Hashtable<String, MiniThread> processThreads = new Hashtable<String, MiniThread>();
	
	protected MiniSemaphore inputSem; // TODO change it to minimutes

	/**
	 * Constructor to the process.
	 * 
	 * @param user
	 *            Owner of the process
	 * @param pid
	 *            Pid of the process
	 */
	public MiniProcess(String user, String pid)
	{
		this.pid = pid;
		this.user = user;
		inputSem = new MiniSemaphore(1);
	}

	/**
	 * Getter for the Pid of the process.
	 * 
	 * @return Pid of the process.
	 */
	public String getPid()
	{
		return pid;
	}

	/**
	 * Getter for the name of the process.
	 * 
	 * @return Name of the process.
	 */
	public String getName()
	{
		return name;
	}

	/**
	 * Getter for the owner of the process.
	 * 
	 * @return Owner of the process.
	 */
	public String getUser()
	{
		return user;
	}

	/**
	 * Getter for the description of the process.
	 * 
	 * @return Description of the process.
	 */
	public String getDescription()
	{
		return description;
	}

	/**
	 * Gets the number of threads owned by the process.
	 * 
	 * @return Number of threads owned by the process.
	 */
	public int getThreadCount()
	{
		return processThreads.size();
	}

	/**
	 * Gets the thread with the given id owned by this process.
	 * 
	 * @param tid
	 *            id of the thread to be returned.
	 * @return Thread owned by this process whose id is given.
	 */
	public MiniThread getThread(String tid)
	{
		return processThreads.get(tid);
	}

	/**
	 * Associates a thread to this process.
	 * 
	 * @param thread
	 *            Thread added to this process.
	 */
	public void addThread(MiniThread thread)
	{
		processThreads.put(thread.getTid(), thread);
	}

	/**
	 * Gets all the threads owned by this process.
	 * 
	 * @return Threads owned by this process.
	 */
	public Hashtable<String, MiniThread> getThreads()
	{
		return processThreads;
	}

	/**
	 * Sets whether this process is suspended by the user or not.
	 * 
	 * @param suspended
	 *            New state of the process.
	 */
	public void setSuspended(boolean suspended)
	{
		this.suspended = suspended;
	}

	/**
	 * Returns the state of the process.
	 * 
	 * @return If true: the process is suspended. Else: the process is running
	 *         normally.
	 */
	public boolean isSuspended()
	{
		return suspended;
	}

	/**
	 * Invoked when a thread terminates and is removed from the system.
	 * 
	 * @param tid
	 *            id of the terminated thread.
	 */
	public void threadTerminated(String tid)
	{
		MiniThread thread = processThreads.remove(tid);
		thread.resumeWaiting();
	}

	/**
	 * Creates the main thread of execution of the process. This is called when
	 * the process is created. The process starts execution when this thread
	 * starts.
	 * 
	 * @param consoleArguments
	 *            Arguments supplied by the user when running the process.
	 * @return Main thread of execution.
	 */
	protected abstract MiniThread createMainThread(String[] consoleArguments);

	public void inputRequest(MiniThread thread)
	{
		System.out.println("d5l in req");
		inputSem.P();
		System.out.println("abl enable in");
		MiniUIManager.getInstance().enableInput(pid, thread.getTid());
		System.out.println("ba3d enable in");
	}

	public void inputRequestCompleted()
	{
		inputSem.V();
	}
}
